﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Net;
using System.Net.Sockets;

namespace For_FS_2013_1_User
{
    class RemoteControl
    {
        private TcpClient client = new TcpClient();
        private TcpListener listener = null;
        private Thread cn;
        private Thread receive;
        private bool stop;
        private string adminLogin;

        public RemoteControl()
        {
            adminLogin = null;
            listener = new TcpListener(IPAddress.Any, 13);
            listener.Start();
            stop = false;
            StartWorking();
        }

        public void StartWorking()
        {
            stop = false;
            CreateThreads();
            cn.Start();
        }

        private void CreateThreads()
        {
            receive = new Thread(ReceiveMessage);
            cn = new Thread(Connect);
        }

        public void Connect()
        {
            while (true)
            {
                client = listener.AcceptTcpClient();
                if (client.Connected)
                {
                    receive.Start();
                    break;
                }
            }
            Console.WriteLine("Admin Connected");
        }

        public void Disconnect()
        {
            if (client != null)
                client.Close();
            stop = true;
            StartWorking();
        }

        private void ReceiveMessage()
        {
            string command = "";
            while (!stop)
            {
                try
                {
                    if (client.Connected)
                    {
                        NetworkStream ns = client.GetStream();
                        while (ns.DataAvailable)
                        {
                            byte[] buffer = new byte[client.Available];
                            ns.Read(buffer, 0, buffer.Length);
                            command += Encoding.Default.GetString(buffer);
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
                if (command != "")
                {
                    Console.WriteLine("Admin->" + command);
                    CommandExecutor(command);
                    command = "";
                }
                Thread.Sleep(100);
            }
        }

        public void Send(string message)
        {
            if (client.Connected)
            {
                NetworkStream ns = client.GetStream();
                if (ns != null)
                {
                    byte[] buffer = Encoding.Default.GetBytes(message);
                    ns.Write(buffer, 0, buffer.Length);
                }
            }
        }

        public string Status()
        {
            if (client.Connected)
                return "Administrator connected";
            else
                return "Administrator does not connected";
        }

        public void CommandExecutor(string command)
        {
            if (command != "")
            {
                string[] task = command.Split(' ');
                if (task[0] == "disconnect")
                {
                    if (Program.authorizedAdmin)
                    {
                        Program.authorizedAdmin = false;
                        Program.users.LogoutAdmin(adminLogin);
                        adminLogin = null;
                    }
                    Disconnect();
                    Console.WriteLine("Administrator disconnected");
                    return;
                }
                if (task[0] == "login")
                {
                    adminLogin = Program.users.AuthorizeAdmin(task[1], task[2]);
                    if (adminLogin != null)
                    {
                        Send("login true");
                        Program.authorizedAdmin = true;
                    }
                    else
                        Send("login false");
                }
                if (task[0] == "online_users")
                {
                    HashSet<string> result = Program.users.ShowOnlineUsers();
                    foreach (string s in result)
                        Send(s);
                }
                if (task[0] == "offline_users")
                {
                    HashSet<string> result = Program.users.ShowOfflineUsers();
                    foreach (string s in result)
                        Send(s);
                }
                if (task[0] == "all_users")
                {
                    HashSet<string> result = Program.users.ShowAllUsers();
                    foreach (string s in result)
                        Send(s);
                }
                if (task[0] == "add_user")
                {
                    if (Program.users.AddUser(task[1], task[2], task[3], task[4], task[5], Convert.ToInt32(task[6])))
                        Send("add_user true");
                    else
                        Send("add_user false");
                }
                if (task[0] == "del_user")
                {
                    if (task[1] == adminLogin)
                        Send("Server->You can't remove your own account from the database!!!!");
                    else
                    {
                        if (Program.users.DelUser(task[1]))
                            Send("Server->User " + task[1] + " removed successfully!!!");
                        else
                            Send("Server->There is no such user in the system's data base!!!");
                    }
                }
                if (task[0] == "change_us_rights")
                {
                    if (task[1] == adminLogin)
                        Send("Server->You can't change your own rights!!!!");
                    else
                    {
                        if (Program.users.ChangeUserRights(task[1]))
                            Send("Server->Rights for user " + task[1] + " has benn changed successfully!!!");
                        else
                            Send("Server->There is no such user in the system's data base!!!");
                    }
                }
                if (task[0] == "reload_files")
                {
                    Program.fm.ReloadFiles();
                }
                if (task[0] == "show_files")
                {
                    HashSet<string> result = Program.fm.GetFiles();
                    foreach (string s in result)
                        Send(s);
                }
                if (task[0]=="change_access_file")
                {
                    if (Program.fm.ChangeFileAccess(task[1]))
                        Send("change_access_file true");
                    else
                        Send("change_access_file false");
                }
                if (task[0] == "show_users")
                {
                    foreach (string s in Program.con.ShowUsers())
                        Send(s);
                }
            }
        }

        public string GetAdmin()
        {
            return adminLogin;
        }

    }
}
